package hikari.persistence.handlersimpl;

import com.gooddies.wiring.annotations.Wire;
import com.gooddies.wiring.annotations.WiringComponent;
import hikari.gui.assets.AssetsTree;
import hikari.managers.Manager3D;
import hikari.objects3d.Basic3dObject;
import hikari.persistence.file.Chunk;
import hikari.persistence.file.FileSection;
import hikari.persistence.persisthandlers.IPersistantObject3dReadHandler;
import hikari.persistence.persisthandlers.PersistantHandler;
import java.io.IOException;
import java.util.List;
import org.swig.jirr.E_MATERIAL_TYPE;
import org.swig.jirr.ISceneManager;
import org.swig.jirr.ITexture;
import org.swig.jirr.MATERIAL_FLAG;
import org.swig.jirr.SColor;
import org.swig.jirr.SMaterial;

/**
 * @author Dmitry
 */
@WiringComponent(singleton = true, lazy = true)
@PersistantHandler(sectionName = "material")
public class MaterialLoadHandler implements IPersistantObject3dReadHandler {
    @Wire
    private AssetsTree assetsTree;

    private MaterialLoadHandler() {
    }
    
    
    @Override
    public Basic3dObject read(ISceneManager sceneManager, Basic3dObject object, FileSection section) throws IOException {
        object.setVisible(section.readBoolean("vis"));
        List<Chunk> subSectionChunks = section.getAllSections();
        for (Chunk chunk : subSectionChunks) {
            switch (chunk.getName()) {
                case "flags": {
                    FileSection flagsSection = section.readSection(chunk);
                    setFlags(object, flagsSection);
                    break;
                }
                case "textures": {
                    FileSection texturesSection = section.readSection(chunk);
                    setTextures(sceneManager, object, texturesSection);
                    break;
                }
                case "colors": {
                    FileSection colorsSection = section.readSection(chunk);
                    setColors(object, colorsSection);
                    break;
                }
            }
        }

        return object;
    }

    private void setTextures(ISceneManager sceneManager, Basic3dObject object, FileSection section) throws IOException {
        List<Chunk> chunks = section.getAllAtributes();
        int textureIndex = 0;
        for (Chunk chunk : chunks) {
            switch (chunk.getName()) {
                case "matType":
                    E_MATERIAL_TYPE matType = E_MATERIAL_TYPE.getTypeFromCPtr(section.readLong(chunk));
                    object.getMeshSceneNode().getMaterial(0).setMaterialType(matType);
                    break;
                case "path":
                    String path = section.readString(chunk);
                    String texturePath = assetsTree.getAbsoluteAssetPathFromRelativePath(path);
                    ITexture texture = sceneManager.getVideoDriver().getTexture(texturePath);
                    object.getMeshSceneNode().getMaterial(0).setTexture(textureIndex, texture);
                    textureIndex++;
                    break;
            }
        }
    }

    private void setColors(Basic3dObject object, FileSection section) throws IOException {
        List<Chunk> colorChunks = section.getAllAtributes();
        SMaterial material = object.getMeshSceneNode().getMaterial(0);
        for (Chunk colorChunk : colorChunks) {
            switch (colorChunk.getName()) {
                case "a": {
                    SColor color = section.readSColor(colorChunk);
                    material.setAmbientColor(color);
                    break;
                }
                case "d": {
                    SColor color = section.readSColor(colorChunk);
                    material.setDiffuseColor(color);
                    break;
                }
                case "e": {
                    SColor color = section.readSColor(colorChunk);
                    material.setEmissiveColor(color);
                    break;
                }
                case "spec": {
                    SColor color = section.readSColor(colorChunk);
                    material.setSpecularColor(color);
                    break;
                }
                case "shin": {
                    float shiness = section.readFloat(colorChunk);
                    material.setShininess(shiness);
                    break;
                }
            }
        }
    }

    private void setFlags(Basic3dObject object, FileSection section) throws IOException {
        List<Chunk> flagChunks = section.getAllAtributes();
        for (Chunk flagChunk : flagChunks) {
            if ("flag".equals(flagChunk.getName())) {
                long[] flagValues = section.readLongs(flagChunk);
                MATERIAL_FLAG flag = MATERIAL_FLAG.getByValue(flagValues[0]);
                boolean value = flagValues[1] == 1 ? true : false;
                object.getMeshSceneNode().setMaterialFlag(flag, value);
            }
        }
    }
}
